import {defineStore} from 'pinia';
import {getToken, removeToken, setToken} from '@/utils/token-utils';
import type {UserInfoState} from "./interface";
import {ElMessage} from 'element-plus'
import {staticRoutes, allAsyncRoutes, anyRoute} from '@/router/routes'
import {reqGetUserInfoAsync, reqPostLoginAsync, reqPostLoginOutAsync} from "@/api/user";
import type {RouteRecordRaw} from "vue-router";
import router from '@/router/index'
import {cloneDeep} from "lodash";

/**
 *此函数 用来过滤出 用户能够看到的页面的菜单
 *
 * allAsyncRoutes:动态路由（功能模块）
 * routes:用户可以查看的动态路由信息
 * */
function filterAsyncRoutes(allAsyncRoutes: RouteRecordRaw[], routes: string[]) {
    return allAsyncRoutes.filter(item => {
        // 将路由中name属性与routeNames中的字符串进行比较，如果相同，则返回true
        if (routes.indexOf(item.name as string) === -1) {
            return false
        }
        // 因为还存在子路由，所以需要递归调用
        // 递归的操作原则是：函数中调用自身函数，但是需要有退出条件
        if (item.children && item.children.length) {
            item.children = filterAsyncRoutes(item.children, routes);
        }
        return true
    })
}

/**
 *将用户能够看到的路由添加到路由表中
 * 用于实现路由跳转
 * */

function addRoutes(routes: RouteRecordRaw[]) {
    // router里原来就已经有了staticRoutes也就是静态路由，所以我只需要将动态和任意追加上去就可以了
    routes.forEach((route) => {
        // 在原来的路由中，动态的将每一个新的路由配置项进行动态的添加
        router.addRoute(route);
    });
}

/**
 * 用户信息
 * @methods setUserInfos 设置用户信息
 */
export const useUserInfoStore = defineStore('userInfo', {

    state: (): UserInfoState => ({
        token: getToken() as string,
        userInfo: {
            routes: [],
            buttons: [],
            roles: [],
            name: "",
            avatar: "",
        },
        menuRoutes: staticRoutes    // 左侧栏的菜单面板
    }),

    actions: {
        // 用户登录
        async Login(username: string, password: string) {
            try {
                const result = await reqPostLoginAsync({username, password})
                // 保存token在本地存储
                setToken(result.token)
                // 更新保存在store的token
                this.token = result.token
            } catch (e) {
                // 返回失败信息
                return Promise.reject(e)
            }
        },

        // 获取用户信息
        async getInfo() {
            try {
                const result = await reqGetUserInfoAsync();
                // 更新用户的信息
                this.userInfo = result
                // 根据用户信息 来渲染该用户 可以看到那些菜单栏列表的显示
                // console.log(this.userInfo.routes);   // 用户可以显示的菜单列表 是大写的 改变成小写

                const routes = []
                // 改变成小写
                for (const itemKey of this.userInfo.routes) {
                    routes.push(itemKey.toLowerCase())
                }
                // 返回一个新数组 里面是 里面是该用户能够看到的菜单内容和使用的功能模块
                const asyncRoutes = filterAsyncRoutes(cloneDeep(allAsyncRoutes), routes);
                // 将静态路由、动态路由、任意路由重新拼接
                // ! 现在仅仅实现的是菜单显示还是不显示的工作，路由的跳转并没有实现（因为没有添加到 staticRoutes路由表中）
                this.menuRoutes = [...staticRoutes, ...asyncRoutes, anyRoute];

                // 我们完整的能够实现路由跳转的路由并没有生成
                // ! 下面实现的是路由的跳转
                addRoutes([...asyncRoutes, anyRoute]);
            } catch (e) {
                // 返回失败的信息
                return Promise.reject(e)
            }
        },

        // 退出登录
        async loginOut() {
            try {
                // 退出登录 使token过期
                await reqPostLoginOutAsync()
                // 清空store中所有的用户信息
                this.reset()
            } catch (e) {
                return Promise.reject(e)
            }
        },

        // 清除所有用户信息
        reset() {
            // 删除local中保存的token
            removeToken()
            // 提交重置用户信息的mutation
            this.token = ''
            this.userInfo = {
                routes: [],
                buttons: [],
                roles: [],
                name: "",
                avatar: "",
            }
        },
    },
});
